package site.wanjiahao.app;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import site.wanjiahao.handler.client.*;
import site.wanjiahao.handler.client.MyChannelDuplexHandler;
import site.wanjiahao.protocol.BasedFrameDecoder;
import site.wanjiahao.protocol.MessageCodec;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
public class Client {

    public static void main(String[] args) {
        // 线程同步通信
        CountDownLatch AWAIT_SIGNAL = new CountDownLatch(1);
        // 原子类
        AtomicBoolean SUCCESS = new AtomicBoolean(false);
        LoggingHandler loggingHandler = new LoggingHandler(LogLevel.DEBUG);
        MessageCodec messageCodec = new MessageCodec();
        ChartResponseMessageHandler chartResponseMessageHandler = new ChartResponseMessageHandler();
        GroupChartResponseMessageHandler groupChartResponseMessageHandler = new GroupChartResponseMessageHandler();
        CreateGroupResponseMessageHandler createGroupResponseMessageHandler = new CreateGroupResponseMessageHandler();
        MyChannelInboundCycleHandlerAdapter myChannelInboundCycleHandlerAdapter = new MyChannelInboundCycleHandlerAdapter(AWAIT_SIGNAL, SUCCESS);
        LoginResponseMessageHandler loginResponseMessageHandler = new LoginResponseMessageHandler(SUCCESS, AWAIT_SIGNAL);
        ListGroupMembersResponseMessageHandler listGroupMembersResponseMessageHandler = new ListGroupMembersResponseMessageHandler();
        ListGroupsResponseMessageHandler listGroupsResponseMessageHandler = new ListGroupsResponseMessageHandler();
        JoinGroupResponseMessageHandler joinGroupResponseMessageHandler = new JoinGroupResponseMessageHandler();
        QuitGroupResponseMessageHandler quitGroupResponseMessageHandler = new QuitGroupResponseMessageHandler();
        IdleStateHandler idleStateHandler = new IdleStateHandler(0, 3, 0);
        MyChannelDuplexHandler myChannelDuplexHandler = new MyChannelDuplexHandler();
        PongMessageHandler pongMessageHandler = new PongMessageHandler();

        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
        // 对于客户端其实是不存在于客户端数据共享问题的
        // 所以在客户端的handler中，全部的handler都可以设置为sharable的
        // 而服务端不同，需要接受多个客户端的请求，需要处理并发问题
        ChannelFuture connectFuture = new Bootstrap()
                .group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) {
                        ch.pipeline()
                                .addLast(loggingHandler)
                                .addLast(new BasedFrameDecoder())
                                .addLast(messageCodec)
                                // 触发邪恶空闲事件
                                .addLast(idleStateHandler)
                                .addLast(myChannelDuplexHandler)
                                .addLast(pongMessageHandler)
                                .addLast(myChannelInboundCycleHandlerAdapter)
                                .addLast(loginResponseMessageHandler)
                                .addLast(chartResponseMessageHandler)
                                // 处理群聊消息
                                .addLast(groupChartResponseMessageHandler)
                                // 处理创建组的信息
                                .addLast(createGroupResponseMessageHandler)
                                // 处理列出组类成员
                                .addLast(listGroupMembersResponseMessageHandler)
                                // 列出所有群聊信息
                                .addLast(listGroupsResponseMessageHandler)
                                // 加入群聊
                                .addLast(joinGroupResponseMessageHandler)
                                // 退出群聊
                                .addLast(quitGroupResponseMessageHandler);
                    }
                })
                .connect("127.0.0.1", 8080);

        try {
            Channel channel = connectFuture.sync().channel();
            // 异步关闭线程
            channel.closeFuture().addListener((ChannelFutureListener) future -> {
                // 结束进程
                eventExecutors.shutdownGracefully();
            });
        } catch (InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
    }

}
